package com.sh.dc.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sh.dc.common.BaseResult;
import com.sh.dc.common.enums.BizCodeEnum;
import com.sh.dc.common.enums.PublishedEnum;
import com.sh.dc.common.pojo.Contants;
import com.sh.dc.common.pojo.bo.AlgoSaveBO;
import com.sh.dc.common.pojo.bo.PutObjectRes;
import com.sh.dc.common.pojo.dto.AlgoDto;
import com.sh.dc.common.pojo.query.AlgoPageQuery;
import com.sh.dc.common.pojo.query.AlgoParseParam;
import com.sh.dc.common.utils.FileUtil;
import com.sh.dc.entity.Algo;
import com.sh.dc.entity.AlgoDetail;
import com.sh.dc.exceptions.BizException;
import com.sh.dc.service.IAlgoDetailService;
import com.sh.dc.service.IAlgoService;
import com.sh.dc.service.IOSSService;
import io.micrometer.common.util.StringUtils;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;

/**
 * <p>
 * 算法 前端控制器
 * </p>
 *
 * @author zhenlan
 * @since 2024-07-11
 */
@RestController
@RequestMapping("/algo")
public class AlgoController {

    @Autowired
    private IAlgoService algoService;

    @Autowired
    private IAlgoDetailService algoDetailService;

    @Autowired
    private IOSSService ossService;

    @PostMapping("/page")
    public BaseResult page(@Valid @RequestBody AlgoPageQuery query) {
        return BaseResult.success(algoService.queryAlgoPage(query));
    }

    @PostMapping("/publish/{id}/{status}")
    public BaseResult publish(@PathVariable("id") Long id, @PathVariable("status") Integer status) {
        if (!PublishedEnum.codeExisted(status)) {
            return BaseResult.fail(BizCodeEnum.ALGO_PUBLISH_STATUS_ERROR);
        }
        Algo algo = algoService.getById(id);
        if (algo == null) {
            return BaseResult.fail(BizCodeEnum.DATA_NOT_EXISTED);
        }
        Date now = new Date();
        if (PublishedEnum.PUBLISHED.getCode().equals(status)) {
            algo.setPublishTime(now);
        }
        algo.setPublished(status);
        algo.setUpdateTime(now);
        return BaseResult.success(algoService.updateById(algo));
    }

    @PostMapping("/save")
    @Transactional
    public BaseResult save(@Valid @RequestBody AlgoSaveBO saveBO) throws BizException {
        Algo algo;
        if (saveBO.getId() != null) {
            algo = algoService.getById(saveBO.getId());
            if (algo == null) {
                return BaseResult.fail(BizCodeEnum.ALGO_NOT_EXISTED);
            }
        } else {
            algo = new Algo();
        }

        BeanUtil.copyProperties(saveBO, algo);
        Date now = new Date();
        algo.setUpdateTime(now);
        algoService.saveOrUpdate(algo);

        QueryWrapper<AlgoDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("algo_id", algo.getId());
        AlgoDetail algoDetailDB = algoDetailService.getOne(queryWrapper);
        if (algoDetailDB == null) {
            algoDetailDB = new AlgoDetail();
            algoDetailDB.setAlgoId(algo.getId());
        }
        if (StringUtils.isNotBlank(saveBO.getAlgoSchema())) {
            algoDetailDB.setAlgoSchema(saveBO.getAlgoSchema());
            String objectName = FileUtil.generateAlgoSchemaOssKey(algo.getId());
            PutObjectRes uploadRet = ossService.putObject(objectName, saveBO.getAlgoSchema());
            if (uploadRet.getSuccess()) {
                algoDetailDB.setAlgoSchemaPath(Contants.OSS_PREFIX + objectName);
            } else {
                throw new BizException(BizCodeEnum.ALGO_SAVE_ERROR);
            }
        }
        if (CollectionUtil.isNotEmpty(saveBO.getOperatorParamList())) {
            algoDetailDB.setOperatorParam(JSON.toJSONString(saveBO.getOperatorParamList()));
        }
        if (CollectionUtil.isNotEmpty(saveBO.getGlobalParamList())) {
            algoDetailDB.setGlobalParam(JSON.toJSONString(saveBO.getGlobalParamList()));
        }
        if (CollectionUtil.isNotEmpty(saveBO.getOutputParamList())) {
            algoDetailDB.setGlobalParam(JSON.toJSONString(saveBO.getGlobalParamList()));
        }
        algoDetailService.saveOrUpdate(algoDetailDB);
        return BaseResult.success(algo);
    }

    @PostMapping("/delete/{id}")
    public BaseResult deleteById(@PathVariable("id") Long id) {
        // TODO 先判断是否有算法任务在运行
        algoService.removeById(id);

        HashMap<String, Object> map = new HashMap<>();
        map.put("algo_id", id);
        algoDetailService.removeByMap(map);

        return BaseResult.success();
    }

    @GetMapping("/{id}")
    public BaseResult getById(@PathVariable("id") Long id) {
        Algo algo = algoService.getById(id);
        if (algo == null) {
            return BaseResult.fail(BizCodeEnum.DATA_NOT_EXISTED);
        }
        AlgoDto algoDto = algoService.transferToDto(algo);
        QueryWrapper<AlgoDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("algo_id", algo.getId());
        AlgoDetail algoDetail = algoDetailService.getOne(queryWrapper);
        if (algoDetail != null) {
            algoDto.setAlgoSchema(algoDetail.getAlgoSchema());
            algoDto.setAlgoSchemaPath(algoDetail.getAlgoSchemaPath());
//            if (StringUtils.isNotBlank(algoDetail.getAlgoSchemaPath())) {
//                algoDto.setAlgoSchemaUrl(ossService.signUrl(algoDetail.getAlgoSchemaPath(), 1));
//            }
        }
        return BaseResult.success(algoDto);
    }

    @PostMapping("/parse")
    public BaseResult parse(@Valid @RequestBody AlgoParseParam parseParam) throws BizException {
        return BaseResult.success(algoService.parseAlgoParams(parseParam.getAlgoSchema()));
    }

}
